﻿using System;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;
using System.Data.SqlClient;

namespace GDExtensions
{
    /// <summary>
    /// Extension methods for the <see cref="T:Microsoft.SharePoint.SPList"/> class.
    /// </summary>
    /// <remarks></remarks>
    public static class SPListExtensions
    {
        #region Public Methods
        /// <summary>
        /// Method to grant user/group access to the <paramref name="list"/>.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="id">The <see cref="T:Microsoft.SharePoint.SPGroup"/> or <see cref="T:Microsoft.SharePoint.SPUser"/> ID.</param>
        /// <param name="roleType">The <see cref="T:Microsoft.SharePoint.SPRoleType"/> role for the <paramref name="list"/>.</param>
        /// <remarks></remarks>
        public static void AddSecurityById(this SPList list, int id, SPRoleType roleType)
        {
            // Ensure the list
            if (list != null)
            {
                // Add the security group to the list
                list.AddSecurityById(id, list.ParentWeb.RoleDefinitions.GetByType(roleType));
            }
        }

        /// <summary>
        /// Method to grant user/group access to the <paramref name="list"/>.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="id">The <see cref="T:Microsoft.SharePoint.SPGroup"/> or <see cref="T:Microsoft.SharePoint.SPUser"/> ID.</param>
        /// <param name="roleDefinition">The <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/> role definition for the <paramref name="list"/>.</param>
        /// <remarks></remarks>
        public static void AddSecurityById(this SPList list, int id, SPRoleDefinition roleDefinition)
        {
            // Call the private method
            _AddSecurityById(list, id, roleDefinition);
        }

        /// <summary>
        /// Method to add a security group to a list.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to add.</param>
        /// <param name="roleName">The name of the <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/>.</param>
        /// <remarks></remarks>
        public static void AddSecurityGroup(this SPList list, SPGroup group, string roleName)
        {
            // Ensure the group & list exist
            if (list != null && group != null)
            {
                // Parse the role definitions
                foreach (SPRoleDefinition roleDef in group.ParentWeb.RoleDefinitions)
                {
                    // See if this is the role def we are looking for
                    if (roleDef.Name.Equals(roleName, StringComparison.CurrentCultureIgnoreCase))
                    {
                        // Add the security group to the list
                        list.AddSecurityGroup(group, roleDef);
                    }
                }
            }
        }

        /// <summary>
        /// Method to add a security group to a list.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to add.</param>
        /// <param name="roleType">The <see cref="T:Microsoft.SharePoint.SPRoleType"/> role for the <paramref name="group"/>.</param>
        /// <remarks></remarks>
        public static void AddSecurityGroup(this SPList list, SPGroup group, SPRoleType roleType)
        {
            // Ensure the group & list exist
            if (list != null && group != null)
            {
                // Add the security group to the list
                list.AddSecurityGroup(group, list.ParentWeb.RoleDefinitions.GetByType(roleType));
            }
        }

        /// <summary>
        /// Method to add a security group to a list.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to add.</param>
        /// <param name="roleDefinition">The <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/> role definition for the <paramref name="group"/>.</param>
        /// <remarks></remarks>
        public static void AddSecurityGroup(this SPList list, SPMember group, SPRoleDefinition roleDefinition)
        {
            // Ensure the group exists
            if (group != null)
            {
                // Add the security group
                list.AddSecurityById(group.ID, roleDefinition);
            }
        }

        /// <summary>
        /// Method to clear the list data.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <remarks></remarks>
        public static void ClearData(this SPList list)
        {
            // Clear the list data
            list.ClearData(false);
        }

        /// <summary>
        /// Method to clear the list data.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="clearRecyclingBin">if set to <c>true</c>, clears the recycling bin of the <see cref="T:Microsoft.SharePoint.SPWeb"/>.</param>
        /// <remarks></remarks>
        public static void ClearData(this SPList list, bool clearRecyclingBin)
        {
            // Call the private method
            _ClearData(list, clearRecyclingBin);
        }

        /// <summary>
        /// Method to clear the list permissions.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <remarks></remarks>
        public static void ClearPermissions(this SPList list)
        {
            // Call the private method
            _ClearPermissions(list);
        }

        /// <summary>
        /// Method to create a folder at the root of a list.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="folderName">The name of the <see cref="T:Microsoft.SharePoint.SPFolder"/> folder to create.</param>
        /// <returns>The <paramref name="folderName"/> <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</returns>
        /// <remarks></remarks>
        public static SPFolder CreateFolder(this SPList list, string folderName)
        {
            // Create the list folder
            return list.CreateFolder(list.RootFolder.ServerRelativeUrl, folderName);
        }

        /// <summary>
        /// Method to create a folder.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="url">The URL of the <paramref name="list"/> sub-folder.</param>
        /// <param name="folderName">The name of the <see cref="T:Microsoft.SharePoint.SPFolder"/> folder to create.</param>
        /// <returns>The <paramref name="folderName"/> <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</returns>
        /// <remarks></remarks>
        public static SPFolder CreateFolder(this SPList list, string url, string folderName)
        {
            // Call the private method
            return _CreateFolder(list, url, folderName);
        }

        /// <summary>
        /// Method to create a method template for batch processing
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <returns>The 'Method' template for the <paramref name="list"/>, when calling the <see cref="T:Microsoft.SharePoint.SPWeb"/> ProcessBatchData method.</returns>
        /// <remarks></remarks>
        public static string CreateMethodTemplate(this SPList list)
        {
            // Create the base method template
            return list.CreateMethodTemplate(null);
        }

        /// <summary>
        /// Method to create a method template for batch processing
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="fields">The <see cref="T:Microsoft.SharePoint.SPField"/> fields to include in the method template.</param>
        /// <returns>The 'Method' template for the <paramref name="list"/>, when calling the <see cref="T:Microsoft.SharePoint.SPWeb"/> ProcessBatchData method.</returns>
        /// <remarks></remarks>
        public static string CreateMethodTemplate(this SPList list, string[] fields)
        {
            // Call the private method
            return _CreateMethodTemplate(list, fields);
        }

        /// <summary>
        /// Method to delete list items, given an array of item ids.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="itemIds">The <see cref="T:Microsoft.SharePoint.SPListItem"/> ids to delete.</param>
        /// <remarks></remarks>
        public static void DeleteListItemsById(this SPList list, int[] itemIds)
        {
            // Clear the list data
            list.DeleteListItemsById(itemIds, false);
        }

        /// <summary>
        /// Method to delete list items, given an array of item ids.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="itemIds">The <see cref="T:Microsoft.SharePoint.SPListItem"/> ids to delete.</param>
        /// <param name="clearRecyclingBin">if set to <c>true</c>, clears the recycling bin of the <see cref="T:Microsoft.SharePoint.SPWeb"/>.</param>
        /// <remarks></remarks>
        public static void DeleteListItemsById(this SPList list, int[] itemIds, bool clearRecyclingBin)
        {
            // Call the private method
            _DeleteListItemsById(list, itemIds, clearRecyclingBin);
        }

        /// <summary>
        /// Method to get the <see cref="Microsoft.SharePoint.SPList"/> field by the display or internal name.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="fieldName">The <see cref="T:Microsoft.SharePoint.SPField"/> field name.</param>
        /// <returns>The <see cref="T:Microsoft.SharePoint.SPField"/> field if it exists, else NULL.</returns>
        /// <remarks></remarks>
        public static SPField GetField(this SPList list, string fieldName)
        {
            // Call the private method
            return _GetField(list, fieldName);
        }

        /// <summary>
        /// Method to find a folder.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="folderName">The folder name to search for.</param>
        /// <returns>The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder if it exists, else NULL.</returns>
        public static SPFolder GetFolder(this SPList list, string folderName)
        {
            // Find the folder
            return list.GetFolder(folderName, true);
        }

        /// <summary>
        /// Method to find a folder.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="folderName">The folder name to search for.</param>
        /// <param name="recursiveFl">Flag to search the root folder recursively.</param>
        /// <returns>The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder if it exists, else NULL.</returns>
        public static SPFolder GetFolder(this SPList list, string folderName, bool recursiveFl)
        {
            // Find the folder
            return list.RootFolder.FindSubFolder(folderName, recursiveFl);
        }

        /// <summary>
        /// Method to return a <see cref="T:Microsoft.SharePoint.SPListItem"/> by the specified <paramref name="queryString"/> CAML query
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="queryString">The <see cref="T:Microsoft.SharePoint.SPQuery"/> CAML query.</param>
        /// <returns>If <paramref name="queryString"/> returns <see cref="T:Microsoft.SharePoint.SPListItemCollection"/>, the first <see cref="T:Microsoft.SharePoint.SPListItem"/>, otherwise NULL.</returns>
        /// <remarks></remarks>
        public static SPListItem GetItemByQuery(this SPList list, string queryString)
        {
            // Call the private method
            return _GetItemByQuery(list, queryString);
        }

        /// <summary>
        /// Method to return a <see cref="T:Microsoft.SharePoint.SPListItemCollection"/> by the specified <paramref name="queryString"/> CAML query.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="queryString">The <see cref="T:Microsoft.SharePoint.SPQuery"/> CAML query.</param>
        /// <returns>If <paramref name="queryString"/> returns <see cref="T:Microsoft.SharePoint.SPListItemCollection"/>, the first <see cref="T:Microsoft.SharePoint.SPListItem"/>, otherwise NULL.</returns>
        /// <remarks></remarks>
        public static SPListItemCollection GetItemsByQuery(this SPList list, string queryString)
        {
            // Call the private method
            return _GetItemsByQuery(list, queryString);
        }

        /// <summary>
        /// Method to remove user access to the <paramref name="list"/>.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPListItem"/> item.</param>
        /// <param name="id">The <see cref="T:Microsoft.SharePoint.SPGroup"/> or <see cref="T:Microsoft.SharePoint.SPUser"/> ID.</param>
        /// <remarks></remarks>
        public static void RemoveSecurityById(this SPList list, int id)
        {
            // Call the private method
            _RemoveSecurityById(list, id);
        }

        /// <summary>
        /// Method to remove a security group from a list.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="groupName">The name of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group to remove.</param>
        /// <remarks></remarks>
        public static void RemoveSecurityGroup(this SPList list, string groupName)
        {
            // Remove the security group
            list.RemoveSecurityGroup(list.ParentWeb.GetSecurityGroup(groupName));
        }

        /// <summary>
        /// Method to remove a security group from a list.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to remove.</param>
        /// <remarks></remarks>
        public static void RemoveSecurityGroup(this SPList list, SPGroup group)
        {
            // Ensure the group exists
            if (group != null)
            {
                // Remove the security group
                list.RemoveSecurityById(group.ID);
            }
        }

        /// <summary>
        /// Method to set the display, edit & new form template names.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="templateName">The name of the template.</param>
        /// <remarks></remarks>
        public static void SetTemplateName(this SPList list, string templateName)
        {
            // Set the form templates
            list.SetTemplateName(PAGETYPE.PAGE_DISPLAYFORM, templateName);
            list.SetTemplateName(PAGETYPE.PAGE_EDITFORM, templateName);
            list.SetTemplateName(PAGETYPE.PAGE_NEWFORM, templateName);
        }

        /// <summary>
        /// Method to set the list form template, by page type.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="pageType">The <see cref="T:Microsoft.SharePoint.PAGETYPE"/> page type.</param>
        /// <param name="templateName">The name of the template.</param>
        /// <remarks></remarks>
        public static void SetTemplateName(this SPList list, PAGETYPE pageType, string templateName)
        {
            // Call the private method
            _SetTemplateName(list, pageType, templateName);
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Method to grant user/group access to the <paramref name="list"/>.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="id">The <see cref="T:Microsoft.SharePoint.SPGroup"/> or <see cref="T:Microsoft.SharePoint.SPUser"/> ID.</param>
        /// <param name="roleDefinition">The <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/> role definition for the <paramref name="list"/>.</param>
        /// <remarks></remarks>
        private static void _AddSecurityById(SPList list, int id, SPRoleDefinition roleDefinition)
        {
            SPUser user = default(SPUser);
            SPGroup group = default(SPGroup);

            // Ensure the list & role definition exist
            if (list == null || roleDefinition == null)
            {
                return;
            }

            // Try to get the user
            try
            {
                user = list.ParentWeb.AllUsers.GetByID(id);
            }
            // Else, this is a group
            catch
            {
                try
                {
                    group = list.ParentWeb.SiteGroups.GetByID(id);
                }
                // Error getting the user/group by id
                catch { return; }
            }

            // Create the role assignment
            SPPrincipal principal = user == null ? group as SPPrincipal : user as SPPrincipal;
            SPRoleAssignment assignment = new SPRoleAssignment(principal);

            // Add the role definition
            assignment.RoleDefinitionBindings.Add(roleDefinition);

            // Ensure the folder has unique role assignments
            if (!list.HasUniqueRoleAssignments)
            {
                // Break the inheritance
                list.BreakRoleInheritance(true);
            }

            // Add the group to the list
            list.RoleAssignments.Add(assignment);
        }

        /// <summary>
        /// Method to clear the list data.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="clearRecyclingBin">if set to <c>true</c>, clears the recycling bin of the <see cref="T:Microsoft.SharePoint.SPWeb"/>.</param>
        /// <remarks></remarks>
        private static void _ClearData(SPList list, bool clearRecyclingBin)
        {
            // Ensure the list exists and contains items
            if (list == null || list.ItemCount == 0)
            {
                return;
            }

            // Create the batch methods xml
            StringBuilder methods = new StringBuilder(
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<ows:Batch OnError=\"Continue\">");

            // Create the method format template
            string methodFormat = list.CreateMethodTemplate();

            // Get the list items
            SPListItemCollection items = list.GetItems(new SPQuery()
            {
                ItemIdQuery = true,
                Query = "",
                RowLimit = (uint)list.ItemCount
            });

            // Parse the list items
            for (int i = 0; i < items.Count; i++)
            {
                // Add the method to the batchMethods
                methods.AppendFormat(methodFormat, items[i].ID, items[i].ID, "Delete");
            }

            // Add the closing tag
            methods.Append("</ows:Batch>");

            // Process the batch methods
            list.ParentWeb.ProcessBatchData(methods.ToString());

            // See if we are clearing the recycling bin
            if (clearRecyclingBin)
            {
                list.ParentWeb.RecycleBin.DeleteAll();
            }
        }

        /// <summary>
        /// Method to clear the list permissions.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <remarks></remarks>
        private static void _ClearPermissions(SPList list)
        {
            // Ensure the list exists
            if (list == null) { return; }

            // Ensure the list contains role assignments
            if (list.RoleAssignments.Count < 1) { return; }

            // Break the role inheritance
            list.BreakRoleInheritance(false);

            // Parse the role assignments
            for (int i = list.RoleAssignments.Count - 1; i >= 0; i--)
            {
                // Clear the current role assignement
                list.RoleAssignments.Remove(i);
            }

            // Get the associated owners group
            SPGroup ownersGroup = list.ParentWeb.GetAssociatedSecurityGroup(AssociatedSecurityGroups.Owners);
            if (ownersGroup != null)
            {
                // Add the owners group by default, and give it full control
                list.AddSecurityGroup(ownersGroup, SPRoleType.Administrator);
            }
        }

        /// <summary>
        /// Method to create a folder.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="url">The URL of the <paramref name="list"/> sub-folder.</param>
        /// <param name="folderName">The name of the <see cref="T:Microsoft.SharePoint.SPFolder"/> folder to create.</param>
        /// <returns>The <paramref name="folderName"/> <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</returns>
        /// <remarks></remarks>
        private static SPFolder _CreateFolder(SPList list, string url, string folderName)
        {
            // Ensure the list exists
            if (list == null) { return default(SPFolder); }

            // Ensure the folder doesn't already exist
            if (list.ParentWeb.GetFolder(SPUrlUtility.CombineUrl(url, folderName)).Exists) { return default(SPFolder); }

            // Create the list folder
            SPListItem folderItem = list.Items.Add(url, SPFileSystemObjectType.Folder, folderName);

            // Set the title field, if it exists
            if (list.Fields.ContainsField("Title"))
            {
                folderItem[SPBuiltInFieldId.Title] = folderName;
            }

            // Save it
            folderItem.SystemUpdate();

            // Return the folder object
            return folderItem.Folder;
        }

        /// <summary>
        /// Method to create a method template for batch processing
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="fields">The <see cref="T:Microsoft.SharePoint.SPField"/> fields to include in the method template.</param>
        /// <returns>The 'Method' template for the <paramref name="list"/>, when calling the <see cref="T:Microsoft.SharePoint.SPWeb"/> ProcessBatchData method.</returns>
        /// <remarks></remarks>
        private static string _CreateMethodTemplate(SPList list, string[] fields)
        {
            string template =
                "<Method ID='{0}'>" +
                "<SetList>" + list.ID + "</SetList>" +
                "<SetVar Name='ID'>{1}</SetVar>" +
                "<SetVar Name='Cmd'>{2}</SetVar>";

            // Ensure the fields exists
            if (fields != null && fields.Length > 0)
            {
                // Set the current index
                int idx = 3;

                // Parse the fields
                foreach (string field in fields)
                {
                    template += "<SetVar Name='urn:schemas-microsoft-com:office:office#" + field +
                        "'>{" + (idx++) + "}</SetVar>";
                }
            }

            // Add the closing tag and return it
            template += "</Method>";
            return template;
        }

        /// <summary>
        /// Method to delete list items, given an array of item ids.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="itemIds">The <see cref="T:Microsoft.SharePoint.SPListItem"/> ids to delete.</param>
        /// <param name="clearRecyclingBin">if set to <c>true</c>, clears the recycling bin of the <see cref="T:Microsoft.SharePoint.SPWeb"/>.</param>
        /// <remarks></remarks>
        private static void _DeleteListItemsById(SPList list, int[] itemIds, bool clearRecyclingBin)
        {
            // Ensure the list exists, contains items and the item id array has values
            if (list == null || list.ItemCount == 0 || itemIds.Length == 0)
            {
                return;
            }

            // Create the batch methods xml
            StringBuilder methods = new StringBuilder(
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<ows:Batch OnError=\"Continue\">");

            // Create the method format template
            string methodFormat = list.CreateMethodTemplate();

            // Get the list items
            SPListItemCollection items = list.GetItems(new SPQuery()
            {
                ItemIdQuery = true,
                Query = "",
                RowLimit = (uint)list.ItemCount
            });

            // Parse the item ids
            for (int i = 0; i < itemIds.Length; i++)
            {
                // Add the method to the batchMethods
                methods.AppendFormat(methodFormat, itemIds[i], itemIds[i], "Delete");
            }

            // Add the closing tag
            methods.Append("</ows:Batch>");

            // Process the batch methods
            list.ParentWeb.ProcessBatchData(methods.ToString());

            // See if we are clearing the recycling bin
            if (clearRecyclingBin)
            {
                list.ParentWeb.RecycleBin.DeleteAll();
            }
        }

        /// <summary>
        /// Method to get the <see cref="Microsoft.SharePoint.SPList"/> field by the display or internal name.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="fieldName">The <see cref="T:Microsoft.SharePoint.SPField"/> field name.</param>
        /// <returns>The <see cref="T:Microsoft.SharePoint.SPField"/> field if it exists, else NULL.</returns>
        /// <remarks></remarks>
        private static SPField _GetField(SPList list, string fieldName)
        {
            SPField field = default(SPField);

            // Ensure the list exists
            if (list != null)
            {
                // Try to get the field by the static name
                field = list.Fields.TryGetFieldByStaticName(fieldName);
                if (field == null)
                {
                    // Try to get the field by the display name
                    try { field = list.Fields.GetField(fieldName); }
                    catch
                    {
                        // Try to get it by the internal name
                        try { field = list.Fields.GetFieldByInternalName(fieldName); }
                        catch { }
                    }
                }
            }

            // Return the field
            return field;
        }

        /// <summary>
        /// Method to return a <see cref="T:Microsoft.SharePoint.SPListItem"/> by the specified <paramref name="queryString"/> CAML query
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="queryString">The <see cref="T:Microsoft.SharePoint.SPQuery"/> CAML query.</param>
        /// <returns>If <paramref name="queryString"/> returns <see cref="T:Microsoft.SharePoint.SPListItemCollection"/>, the first <see cref="T:Microsoft.SharePoint.SPListItem"/>, otherwise NULL.</returns>
        /// <remarks></remarks>
        private static SPListItem _GetItemByQuery(SPList list, string queryString)
        {
            // Get the list items for this query
            SPListItemCollection items = list.GetItemsByQuery(queryString, 1);
            if (items != null && items.Count > 0)
            {
                return items[0];
            }

            return default(SPListItem);
        }

        /// <summary>
        /// Method to return a <see cref="T:Microsoft.SharePoint.SPListItemCollection"/> by the specified <paramref name="queryString"/> CAML query.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="queryString">The <see cref="T:Microsoft.SharePoint.SPQuery"/> CAML query.</param>
        /// <returns>If <paramref name="queryString"/> returns <see cref="T:Microsoft.SharePoint.SPListItemCollection"/>, the first <see cref="T:Microsoft.SharePoint.SPListItem"/>, otherwise NULL.</returns>
        /// <remarks></remarks>
        private static SPListItemCollection _GetItemsByQuery(SPList list, string queryString)
        {
            // Return the list items
            return list.GetItemsByQuery(queryString, list.ItemCount);
        }

        /// <summary>
        /// Method to remove access to the <paramref name="list"/>.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPListItem"/> item.</param>
        /// <param name="id">The <see cref="T:Microsoft.SharePoint.SPGroup"/> or <see cref="T:Microsoft.SharePoint.SPUser"/> ID.</param>
        /// <remarks></remarks>
        private static void _RemoveSecurityById(SPList list, int id)
        {
            // Ensure the list exists
            if (list != null)
            {
                // Ensure the list is not inheriting permissions
                if (!list.HasUniqueRoleAssignments)
                {
                    // Break the inheritance
                    list.BreakRoleInheritance(true);
                }

                // Remove the security group from the list
                list.RoleAssignments.RemoveById(id);
            }
        }

        /// <summary>
        /// Method to set the list form template, by page type.
        /// </summary>
        /// <param name="list">The <see cref="T:Microsoft.SharePoint.SPList"/> list.</param>
        /// <param name="pageType">The <see cref="T:Microsoft.SharePoint.PAGETYPE"/> page type.</param>
        /// <param name="templateName">The name of the template.</param>
        /// <remarks></remarks>
        private static void _SetTemplateName(SPList list, PAGETYPE pageType, string templateName)
        {
            // Get the form
            SPForm form = list.Forms[pageType];
            if (form != null)
            {
                // Get the file
                SPFile file = list.ParentWeb.GetFile(SPUrlUtility.CombineUrl(list.ParentWebUrl, form.Url));
                if (file != null && file.Exists)
                {
                    // Get the web part manager
                    using (SPLimitedWebPartManager wpMgr = file.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared))
                    {
                        // Parse the web parts on the page
                        foreach (WebPart wp in wpMgr.WebParts)
                        {
                            // See if this is the list form web part
                            if (wp is ListFormWebPart)
                            {
                                // Allow unsafe updates
                                wpMgr.Web.AllowUnsafeUpdates = true;

                                // Set the template name
                                (wp as ListFormWebPart).TemplateName = templateName;

                                // Save the changes
                                wpMgr.SaveChanges(wp);

                                // Disallow unsafe updates
                                wpMgr.Web.AllowUnsafeUpdates = false;
                            }
                        }
                    }
                }
            }
        }
        #endregion

        #region Helper Methods
        private static SPListItemCollection GetItemsByQuery(this SPList list, string queryString, int maxItems)
        {
            // Create the query
            SPQuery query = new SPQuery()
            {
                Query = queryString,
                RowLimit = (uint)maxItems,
                ViewAttributes = "Scope=\"Recursive\""
            };

            try
            {
                // Get the list items
                return list.GetItems(query);
            }
            catch { }

            return default(SPListItemCollection);
        }
        #endregion
    }
}
